package id.laskarmedia.opnvpn_flutter;

import androidx.annotation.NonNull;

import id.laskarmedia.opnvpn_flutter.handler.VPNEventHandler;
import id.laskarmedia.opnvpn_flutter.handler.VPNEventManager;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;


/**
 * OpnvpnFlutterPlugin is a Flutter plugin for handling VPN events and communication between Flutter and native Android.
 * It implements the FlutterPlugin, MethodCallHandler, and ActivityAware interfaces.
 */
public class OpnvpnFlutterPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
    private MethodChannel vpnControlMethod;
    private EventChannel vpnStageEvent;
    private EventChannel.EventSink vpnStageSink;
    private static final String EVENT_CHANNEL_VPN_STAGE = "id.laskarmedia.openvpn_flutter/vpnstage";
    private static final String METHOD_CHANNEL_VPN_CONTROL = "id.laskarmedia.openvpn_flutter/vpncontrol";

    /**
     * Called when the plugin is attached to the FlutterEngine.
     *
     * @param binding The FlutterPluginBinding instance containing the binary messenger and other plugin-related information.
     */
    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
        vpnStageEvent = new EventChannel(binding.getBinaryMessenger(), EVENT_CHANNEL_VPN_STAGE);
        vpnControlMethod = new MethodChannel(binding.getBinaryMessenger(), METHOD_CHANNEL_VPN_CONTROL);

        vpnStageEvent.setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                vpnStageSink = events;
            }

            @Override
            public void onCancel(Object arguments) {
                if (vpnStageSink != null) {
                    vpnStageSink.endOfStream();
                }
            }
        });

        vpnControlMethod.setMethodCallHandler(this);
    }

    /**
     * Handles the method call received from Flutter.
     *
     * @param call   The method call object containing the method name and arguments.
     * @param result The result object to send the method call result back to Flutter.
     */
    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        VPNEventHandler vpnEventHandler = VPNEventManager.getEventHandler(call.method);
        if (vpnEventHandler != null) {
            vpnEventHandler.config(vpnStageSink);
            vpnEventHandler.handler(call, result);
        } else {
            result.error("Not found", "VPN event handler not found", null);
        }
    }

    /**
     * Called when the plugin is detached from the FlutterEngine.
     *
     * @param binding The FlutterPluginBinding instance containing the binary messenger and other plugin-related information.
     */
    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        vpnControlMethod.setMethodCallHandler(null);
        vpnStageEvent.setStreamHandler(null);
    }


    /**
     * Called when the plugin is attached to the activity.
     *
     * @param binding The ActivityPluginBinding instance containing the activity and other plugin-related information.
     */
    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        ContextHelper.setActivity(binding.getActivity());
    }

    /**
     * Called when the plugin is detached from the activity due to configuration changes.
     */
    @Override
    public void onDetachedFromActivityForConfigChanges() {

    }

    /**
     * Called when the plugin is reattached to the activity after configuration changes.
     *
     * @param binding The ActivityPluginBinding instance containing the activity and other plugin-related information.
     */
    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
        ContextHelper.setActivity(binding.getActivity());
    }

    /**
     * Called when the plugin is detached from the activity.
     */
    @Override
    public void onDetachedFromActivity() {
        ContextHelper.setActivity(null);
    }
}
